package com.wngbms.websocket.controller;

import com.wngbms.websocket.user.UserHook;
import com.wngbms.websocket.support.SpringBeanSupport;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}/{timestamp}")
public class SocketHandler {

    UserHook userHook;

    RedissonClient redissonClient;

    private static final AtomicInteger onlineCount = new AtomicInteger(0);

    public SocketHandler() {
        log.info("new SocketHandler");
    }

    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) {
        onlineCount.incrementAndGet(); // 在线数加1
        log.info("有新连接加入：sessionId:{} userId:{}，当前在线人数为：{}", session.getId(), userId, onlineCount.get());

        if (userHook == null) {
            userHook = SpringBeanSupport.getBean(UserHook.class);
        }

        if (redissonClient == null) {
            redissonClient = SpringBeanSupport.getBean(RedissonClient.class);
        }

        RLock fairLock = redissonClient.getFairLock(userId);
        fairLock.lock(30, TimeUnit.SECONDS);
        try {
            // todo 加分布式锁 防止同一用户并发登录
            userHook.putUserSession(userId, session);
        } finally {
            fairLock.unlock();
        }
    }

    @OnClose
    public void onClose(@PathParam("userId") String userId, Session session) {
        onlineCount.decrementAndGet(); // 在线数减1
        log.info("有一连接关闭：sessionId:{} userId:{}，当前在线人数为：{}", session.getId(), userId, onlineCount.get());

        userHook.removeUserSession(userId, session);
    }

    @OnMessage
    public void onMessage(@PathParam("userId") String userId, String message, Session session) {
        log.info("服务端收到客户端[{}] userId:{}, 的消息:{}", session.getId(), userId, message);
//        int i = 1 / 0;
        this.sendMessage("Hello, " + message, session);

        if (userHook == null) {
            userHook = SpringBeanSupport.getBean(UserHook.class);
        }
        userHook.updateUserInfo(userId);
    }

    @OnError
    public void onError(@PathParam("userId") String userId, Session session, Throwable throwable) {
        log.error("发生错误: sessionId:{} userId:{}", session.getId(), userId, throwable);
        userHook.removeUserSession(userId,session);
    }

    /**
     * 服务端发送消息给客户端
     */
    private void sendMessage(String message, Session toSession) {
        try {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败：{}", e);
        }
    }

}
